﻿unit EventHandler;

interface

uses
  Winapi.Windows, System.Classes, System.SysUtils, Protocol;

type

  //事件
  TOnActFuncPtrEvent = function(): FN_HANDLE_STATUS of object;

  //THandlerEvent结构
  PTHandlerEvent = ^THandlerEvent;
  THandlerEvent = packed record
    m_nEventCmd:     Cardinal;                              //外部事件(触发)
    m_sEventName:    array[0..30] of Char;                  //事件名称
    m_ActFuncEvent:  TOnActFuncPtrEvent;                    //事件绑定
  end;

  //事件分发
  TIEventHandler = class
  private
    m_nBaseEventCmd:  Cardinal;                             //事件基数(cmd)
    m_nSplitStep:     Byte;                                 //拼包步骤
    m_nPackErrorTime: Cardinal;                             //数据拼包错误次数
  public
    procedure SplitStepAddStep;                             //步长加1
    procedure ReSetSplitStep(m_bErrorSet: Boolean = True);  //重新初始化步长
  published
    property FSplitStep: Byte read m_nSplitStep;
  public
    m_ActionFunctions:  TList;                              //事件列表
  public
    procedure RegisterEvent(m_nEventCmd: Cardinal; m_sEventName: string; m_ActFuncEvent: TOnActFuncPtrEvent);
    //默认使用索引分发
    function HandleEvent(m_EventCmd: Cardinal; m_bUsedIndex: Boolean = False): FN_HANDLE_STATUS; overload;
    function HandleEvent(m_EventName: PChar): FN_HANDLE_STATUS; overload;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

constructor TIEventHandler.Create;
begin
  inherited Create;
  m_ActionFunctions := TList.Create;
  m_nSplitStep := 1;
  m_nPackErrorTime := 0;
end;

destructor TIEventHandler.Destroy;
var
  i: Integer;
begin
  if m_ActionFunctions.Count>0 then begin
    for i := 0 to m_ActionFunctions.Count - 1 do
      Dispose(m_ActionFunctions[I]);
  end;
  FreeAndNil(m_ActionFunctions);
  inherited Destroy;
end;

procedure TIEventHandler.ReSetSplitStep(m_bErrorSet: Boolean);
begin
  m_nSplitStep := 1;
  if m_bErrorSet then m_nPackErrorTime := m_nPackErrorTime + 1;
end;

procedure TIEventHandler.SplitStepAddStep;
begin
  Inc(m_nSplitStep);
  m_nPackErrorTime := 0;
end;

procedure TIEventHandler.RegisterEvent(m_nEventCmd: Cardinal; m_sEventName: string;
  m_ActFuncEvent: TOnActFuncPtrEvent);
var
 pHandEvent: PTHandlerEvent;
begin
  New(pHandEvent);
  pHandEvent^.m_nEventCmd := m_nEventCmd;
  StrPCopy(pHandEvent^.m_sEventName, m_sEventName);
  pHandEvent^.m_ActFuncEvent := m_ActFuncEvent;
  m_ActionFunctions.Add(pHandEvent);
end;

function TIEventHandler.HandleEvent(m_EventCmd: Cardinal; m_bUsedIndex: Boolean): FN_HANDLE_STATUS;
var
 i: Integer;
 m_nIndex: Integer;
 m_nItemCount: Integer;
begin
  if m_ActionFunctions.Count > 0 then
  begin
    m_nItemCount := m_ActionFunctions.Count;
    if m_bUsedIndex then
    begin
      m_nIndex := m_EventCmd - m_nBaseEventCmd;
      if (m_nIndex >= 0) and (m_nIndex < m_nItemCount) then
      begin
        if Assigned(PTHandlerEvent(m_ActionFunctions[m_nIndex])^.m_ActFuncEvent) then
        begin
          Result := PTHandlerEvent(m_ActionFunctions[m_nIndex])^.m_ActFuncEvent;
          Exit;
        end;
      end;
    end
    else
    begin
      for i := 0 to m_ActionFunctions.Count - 1 do
      begin
        if PTHandlerEvent(m_ActionFunctions[i])^.m_nEventCmd = m_EventCmd then
        begin
          if Assigned(PTHandlerEvent(m_ActionFunctions[i])^.m_ActFuncEvent) then
          begin
            Result := PTHandlerEvent(m_ActionFunctions[i])^.m_ActFuncEvent;
            Exit;
          end;
        end;
      end;
    end;
  end;
  Result :=  FN_HANDLE_NOTEXIST;
end;

function TIEventHandler.HandleEvent(m_EventName: PChar): FN_HANDLE_STATUS;
var
 i: Integer;
begin
  if m_ActionFunctions.Count > 0 then
  begin
    for i := 0 to m_ActionFunctions.Count - 1 do begin
      if PTHandlerEvent(m_ActionFunctions[I])^.m_sEventName = m_EventName then
      begin
        if Assigned(PTHandlerEvent(m_ActionFunctions[I])^.m_ActFuncEvent) then
        begin
          Result := PTHandlerEvent(m_ActionFunctions[I])^.m_ActFuncEvent;
          Exit;
        end;
      end;
    end;
  end;
  Result :=  FN_HANDLE_NOTEXIST;
end;

end.


